﻿int fps = 100;
long currentTime, lastTime;
int w = 60, h = 30;// 设置屏幕大小
int xuanxiang = 0;
ConsoleKeyInfo key;
ConsoleKeyInfo move;
Selection sel;
Direction dir;
Pos pos;
int nowScence = 0;//设置场景编号
string fileName;
int[,] map;

#region 输入
void Input()
{
    if (nowScence == 0)//是否转换场景
    {
        key = Console.ReadKey(true);
        //开始界面选项控制
        switch (key.Key)
        {
            case ConsoleKey.UpArrow:
            case ConsoleKey.W:
                sel = Selection.Up;
                break;
            case ConsoleKey.DownArrow:
            case ConsoleKey.S:
                sel = Selection.down;
                break;
            case ConsoleKey.J:
                sel = Selection.jj;
                break;
        }
    }
    else if (nowScence == 1)//是否转换场景
    {
        move = Console.ReadKey(true);  // 参数控制是否显示字符
        //移动
        switch (move.Key)
        {
            case ConsoleKey.UpArrow:
            case ConsoleKey.W:
                dir = Direction.Up;
                break;
            case ConsoleKey.DownArrow:
            case ConsoleKey.S:
                dir = Direction.Down;
                break;
            case ConsoleKey.LeftArrow:
            case ConsoleKey.A:
                dir = Direction.Left;
                break;
            case ConsoleKey.RightArrow:
            case ConsoleKey.D:
                dir = Direction.Right;
                break;
            default:
                break;

        }
    }
}
#endregion

void DrawMap(int[,] data)
{
    for (int i = 0; i < data.GetLength(0); i++)
    {
        for (int j = 0; j < data.GetLength(1); j++)
        {
            // 根据地图数据 绘制相应符号
            //if (data[i, j] == 0)
            //{
            //    // 如果地图数据是“墙” 那我就画墙
            //    Console.SetCursorPosition(j, i); Console.Write("X");
            //}
            switch (data[i, j])
            {
                case (int)MapType.Wall:
                    Console.ForegroundColor = ConsoleColor.DarkGray;
                    Console.SetCursorPosition(j, i);
                    Console.Write("X");
                    break;
                case (int)MapType.None:
                    Console.SetCursorPosition(j, i); 
                    Console.Write(" ");
                    break;
                case (int)MapType.Box:
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.SetCursorPosition(j, i); 
                    Console.Write("a");
                    break;
                case (int)MapType.Exit:
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.SetCursorPosition(j, i); 
                    Console.Write("O");
                    break;
            }
        }
    }
}

void Move()
{
    // 根据移动方向修改坐标
    switch (dir)
    {
        case Direction.Up:
            pos.y--;
            break;
        case Direction.Down:
            pos.y++;
            break;
        case Direction.Left:
            pos.x--;
            break;
        case Direction.Right:
            pos.x++;
            break;
    }
}

// 获取下一格坐标
Pos GetNextPos()
{
    Pos next;
    next.x = next.y = 0;
    next.x0 = next.y0 = 0;
    switch (dir)
    {
        case Direction.Up:
            next.x = pos.x;
            next.y = pos.y - 1;
            break;
        case Direction.Down:
            next.x = pos.x;
            next.y = pos.y + 1;
            break;
        case Direction.Left:
            next.x = pos.x - 1;
            next.y = pos.y;
            break;
        case Direction.Right:
            next.x = pos.x + 1;
            next.y = pos.y;
            break;
    }
    return next;
}

// 获取下下一格坐标
Pos GetNextNextPos()
{
    Pos next;
    next.x = next.y = 0;
    next.x0 = next.y0 = 0;
    switch (dir)
    {
        case Direction.Up:
            next.x = pos.x;
            next.y = pos.y - 2;
            break;
        case Direction.Down:
            next.x = pos.x;
            next.y = pos.y + 2;
            break;
        case Direction.Left:
            next.x = pos.x - 2;
            next.y = pos.y;
            break;
        case Direction.Right:
            next.x = pos.x + 2;
            next.y = pos.y;
            break;
    }
    return next;
}

// 根据坐标获得地图数据
int GetMapType(Pos pos)
{
    return map[pos.y, pos.x];
}

// 修改地图数据
void ChangeMapType(Pos pos, int type)
{
    map[pos.y, pos.x] = type;
}

#region 初始化
void Init()
{
    //隐藏光标
    Console.CursorVisible = false;
    //设置标题
    Console.Title = "推箱子";
    //设置控制台变量
    int w = 60, h = 30;
    //设置控制台大小
    Console.SetWindowSize(w, h);
    Console.SetBufferSize(w + 20, h + 20);
    //开始界面选项
    sel = Selection.None;
    //出生点坐标
    pos.x = w / 2;
    pos.y = h / 2;
    //移动
    dir = Direction.None;

    fileName = "../../../map.csv";
    map = new int[30, 60];

    if (File.Exists(fileName))
    {
        // 读取文件, 这里using表示只在这里读取(使用？)，出了之后释放？以免内存泄漏
        using (StreamReader sr = new StreamReader(fileName))
        {
            string data = sr.ReadToEnd();
            // 字符串分割 Split, 这里的文本中用",""换行"分离
            string[] lines = data.Split('\n'); // 分隔的也可使字符串
            for (int i = 0; i < lines.Length; i++)
            {
                string[] elements = lines[i].Split(',');
                for (int j = 0; j < elements.Length; j++)
                {
                    map[i, j] = int.Parse(elements[j]);
                }
            }
        };
    }
    pos.x0 = pos.x;
    pos.y0 = pos.y;
    dir = Direction.None;
}

#endregion

#region 更新
void Update()
{
    Input();
    if (nowScence == 0)//是否转换场景
    {
        //开始界面选项变化
        switch (sel)
        {
            case Selection.Up:
                --xuanxiang;
                if (xuanxiang < 0)
                {
                    xuanxiang = 0;
                }
                break;
            case Selection.down:
                ++xuanxiang;
                if (xuanxiang > 1)
                {
                    xuanxiang = 1;
                }
                break;
            case Selection.jj:
                if (xuanxiang == 0)
                {
                    nowScence = 1;
                    Console.Clear();
                }
                else
                {
                    Environment.Exit(0);
                }
                break;
            default:
                break;
        }
    }
    else if (nowScence == 1)//是否转换场景
    {
        // 如果撞到墙 就不动
        // if (没有撞到墙) Move();
        // 如何获取角色下一格的坐标？
        // 判断下一格坐标是否是墙->如何根据坐标获取地图数据
        if (GetMapType(GetNextPos()) != (int)MapType.Wall &&
            GetMapType(GetNextPos()) != (int)MapType.Box)
        {
            Move();
        }
        // 如何推动箱子
        // 角色面前有箱子，箱子面前没有障碍物
        // 结果 箱子前进一格，角色前进一格
        if (pos.x == pos.x0 && pos.y == pos.y0 &&
            GetMapType(GetNextPos()) == (int)MapType.Box &&
            GetMapType(GetNextNextPos()) != (int)MapType.Box &&
            GetMapType(GetNextNextPos()) != (int)MapType.Wall)
        {
            // 箱子前进一格
            // 箱子的位置（玩家的前一格）变成空地 箱子的前一格（玩家的前前一格）变成箱子
            ChangeMapType(GetNextPos(), (int)MapType.None);
            ChangeMapType(GetNextNextPos(), (int)MapType.Box);
            Move();
        }
        //switch (dir)
        //{
        //    case Direction.Up:
        //        pos.y--;
        //        break;
        //    case Direction.Down:
        //        pos.y++;
        //        break;
        //    case Direction.Left:
        //        pos.x--;
        //        break;
        //    case Direction.Right:
        //        pos.x++;
        //        break;
        //}
        // 限定范围
        //if (pos.x < 2) pos.x = 2;
        //if (pos.x > w - 4) pos.x = w - 4;
        //if (pos.y < 1) pos.y = 1;
        //if (pos.y > h - 2) pos.y = h - 2;
    }
}

#endregion

#region 渲染
void Render()
{
    if (nowScence == 0)//是否转换场景
    {
        //Console.Clear();
        //设置标题以及位置
        Console.ResetColor();
        Console.SetCursorPosition(w / 2 - 3, h / 4);
        Console.WriteLine("推箱子");
        //设置开始选项
        Console.ForegroundColor = xuanxiang == 0 ? ConsoleColor.Red : ConsoleColor.White;
        Console.SetCursorPosition(w / 2 - 4, h / 4 + 4);
        Console.WriteLine("开始游戏");
        Console.ForegroundColor = xuanxiang == 1 ? ConsoleColor.Red : ConsoleColor.White;
        Console.SetCursorPosition(w / 2 - 4, h / 4 + 6);
        Console.WriteLine("退出游戏");
    }
    else if (nowScence == 1)//是否转换场景
    {
        DrawMap(map);
        //Console.Clear();
        // 画面
        Console.SetCursorPosition(pos.x0, pos.y0);
        Console.Write(" ");
        pos.y0 = pos.y;
        pos.x0 = pos.x;
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.SetCursorPosition(pos.x, pos.y);//设置方块坐标
        Console.Write("@");
        //设置围墙
        //Console.ForegroundColor = ConsoleColor.DarkGray;
    }
}

#endregion

#region 结束
void End()
{

}

#endregion

#region 游戏
void Game()
{
    Init();
    lastTime = DateTime.Now.Ticks;
    while (true)
    {
        Update();
        currentTime = DateTime.Now.Ticks;
        if (currentTime - lastTime > 10_000_000 / fps)
        {
            Render();
            lastTime = DateTime.Now.Ticks;
        }
    }
    End();
}

#endregion
Game();
enum Selection//开始界面选项
{
    None,
    Up,
    down,
    jj,
}
enum Direction//移动
{
    None,
    Up,
    Down,
    Left,
    Right
}
struct Loc//出生点
{
    public int x;
    public int y;
}

struct Pos
{
    public int x;
    public int y;
    public int x0;
    public int y0;
};
enum MapType
{
    Wall,
    None,
    Box,
    Exit
}